package org.lex.swing.fontchooser.jedit;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.lex.swing.widgets.EnhancedDialog;


public class FontChooserDialog extends EnhancedDialog {
	/**
	 * For some reason the default Java fonts show up in the list with .bold,
	 * .bolditalic, and .italic extensions.
	 */
	private static final String[] HIDEFONTS = { ".bold", ".italic" };

	private JButton cancel;

	private JTextField familyField;

	private JList familyList;
	private boolean isOK;
	private JButton ok;
	private JLabel preview;
	private JTextField sizeField;
	private JList sizeList;
	private JTextField styleField;
	private JList styleList;

	public FontChooserDialog(Window parent, Font font) {
		super(parent, "Font", true);
		init(font);
	}

	public void cancel() {
		dispose();
	}

	public Font getSelectedFont() {
		if (!isOK)
			return null;

		int size;
		try {
			size = Integer.parseInt(sizeField.getText());
		} catch (Exception e) {
			size = 12;
		}

		return new Font(familyField.getText(), styleList.getSelectedIndex(), size);
	}

	public void ok() {
		isOK = true;
		dispose();
	}

	private JPanel createTextFieldAndListPanel(String label, JTextField textField, JList list) {
		GridBagLayout layout = new GridBagLayout();
		JPanel panel = new JPanel(layout);

		GridBagConstraints cons = new GridBagConstraints();
		cons.gridx = cons.gridy = 0;
		cons.gridwidth = cons.gridheight = 1;
		cons.fill = GridBagConstraints.BOTH;
		cons.weightx = 1.0f;

		JLabel _label = new JLabel(label);
		layout.setConstraints(_label, cons);
		panel.add(_label);

		cons.gridy = 1;
		Component vs = Box.createVerticalStrut(6);
		layout.setConstraints(vs, cons);
		panel.add(vs);

		cons.gridy = 2;
		layout.setConstraints(textField, cons);
		panel.add(textField);

		cons.gridy = 3;
		vs = Box.createVerticalStrut(6);
		layout.setConstraints(vs, cons);
		panel.add(vs);

		cons.gridy = 4;
		cons.gridheight = GridBagConstraints.REMAINDER;
		cons.weighty = 1.0f;
		JScrollPane scroller = new JScrollPane(list);
		layout.setConstraints(scroller, cons);
		panel.add(scroller);

		return panel;
	}

	private String[] getFontList() {
		String[] nameArray = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
		Vector<String> nameVector = new Vector<String>(nameArray.length);

		for (int i = 0, j; i < nameArray.length; i++) {
			for (j = 0; j < HIDEFONTS.length; j++) {
				if (nameArray[i].indexOf(HIDEFONTS[j]) >= 0)
					break;
			}

			if (j == HIDEFONTS.length)
				nameVector.addElement(nameArray[i]);
		}

		String[] _array = new String[nameVector.size()];
		nameVector.copyInto(_array);
		return _array;
	} // }}}

	private void init(Font font) {
		JPanel content = new JPanel(new BorderLayout());
		content.setBorder(new EmptyBorder(12, 12, 12, 12));
		setContentPane(content);

		JPanel listPanel = new JPanel(new GridLayout(1, 3, 6, 6));

		String[] fonts;
		try {
			fonts = getFontList();
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
			/* fonts = getToolkit().getFontList(); */
			fonts = new String[] { "Broken Java implementation!" };
		}

		JPanel familyPanel = createTextFieldAndListPanel("font-selector.family", familyField = new JTextField(), familyList = new JList(fonts));
		listPanel.add(familyPanel);

		String[] sizes = { "9", "10", "12", "14", "16", "18", "24" };
		JPanel sizePanel = createTextFieldAndListPanel("font-selector.size", sizeField = new JTextField(), sizeList = new JList(sizes));
		listPanel.add(sizePanel);

		String[] styles = { "Plain", "Bold", "Italic", "Bold italic" };

		JPanel stylePanel = createTextFieldAndListPanel("font-selector.style", styleField = new JTextField(), styleList = new JList(styles));
		styleField.setEditable(false);
		listPanel.add(stylePanel);

		familyList.setSelectedValue(font.getFamily(), true);
		familyField.setText(font.getFamily());
		sizeList.setSelectedValue(String.valueOf(font.getSize()), true);
		sizeField.setText(String.valueOf(font.getSize()));
		styleList.setSelectedIndex(font.getStyle());
		styleField.setText((String) styleList.getSelectedValue());

		ListHandler listHandler = new ListHandler();
		familyList.addListSelectionListener(listHandler);
		sizeList.addListSelectionListener(listHandler);
		styleList.addListSelectionListener(listHandler);

		content.add(BorderLayout.NORTH, listPanel);

		preview = new JLabel("font-selector.long-text");
		preview.setBorder(new TitledBorder("Preview"));

		updatePreview();

		Dimension prefSize = preview.getPreferredSize();
		prefSize.height = 50;
		preview.setPreferredSize(prefSize);

		content.add(BorderLayout.CENTER, preview);

		JPanel buttons = new JPanel();
		buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
		buttons.setBorder(new EmptyBorder(12, 0, 0, 0));
		buttons.add(Box.createGlue());

		ok = new JButton("OK");
		ok.addActionListener(new ActionHandler());
		getRootPane().setDefaultButton(ok);
		buttons.add(ok);

		buttons.add(Box.createHorizontalStrut(6));

		cancel = new JButton("Cancel");
		cancel.addActionListener(new ActionHandler());
		buttons.add(cancel);

		buttons.add(Box.createGlue());

		content.add(BorderLayout.SOUTH, buttons);

		pack();
		setLocationRelativeTo(getParent());
		setVisible(true);
	}

	private void updatePreview() {
		String family = familyField.getText();
		int size;
		try {
			size = Integer.parseInt(sizeField.getText());
		} catch (Exception e) {
			size = 12;
		}
		int style = styleList.getSelectedIndex();

		preview.setFont(new Font(family, style, size));
	}

	class ActionHandler implements ActionListener {
		public void actionPerformed(ActionEvent evt) {
			if (evt.getSource() == ok)
				ok();
			else if (evt.getSource() == cancel)
				cancel();
		}
	}

	class ListHandler implements ListSelectionListener {
		public void valueChanged(ListSelectionEvent evt) {
			Object source = evt.getSource();
			if (source == familyList) {
				String family = (String) familyList.getSelectedValue();
				if (family != null)
					familyField.setText(family);
			} else if (source == sizeList) {
				String size = (String) sizeList.getSelectedValue();
				if (size != null)
					sizeField.setText(size);
			} else if (source == styleList) {
				String style = (String) styleList.getSelectedValue();
				if (style != null)
					styleField.setText(style);
			}

			updatePreview();
		}
	}
}
